<template>
  <div class="photo-container">
    <photo-box
      v-for="photo in wrappedPhotos"
      :key="photo.index"
      :isCenter="photo.isCenter"
      :index="photo.index"
      :src="photo.src"
      :title="photo.title"
      :desc="photo.desc"
      :x="photo.x"
      :y="photo.y"
      :rotate="photo.rotate"
      :isInverse="photo.isInverse"
      @click="handleClick"
    />

    <photos-controller :photos="wrappedPhotos"
                       @click="handleClick"/>
  </div>
</template>

<script>
  import _ from 'lodash'
  import PhotoBox from './PhotoBox'
  import PhotosController from './PhotosController'

  const BOX_SIZE = {
    WIDTH: 300,
    HEIGHT: 250,
  }

  const ROTATE_RANGE = {
    MIN: -30,
    MAX: 30,
  }

  const randomPosition = (range) => {
    return {
      x: _.random(...range.x),
      y: _.random(...range.y),
      rotate: _.random(ROTATE_RANGE.MIN, ROTATE_RANGE.MAX)
    }
  }

  export default {
    name: 'photos-container',
    props: ['photos'],
    components: { PhotoBox, PhotosController },
    data () {
      const wrapPhoto = (photo, index) => {
        photo.index = index
        photo.x = 0
        photo.y = 0
        photo.rotate = 0
        photo.isCenter = false
        photo.isInverse = false
      }

      const wrappedPhotos = _.chain(this.$props.photos)
                             .clone()
                             .forEach(wrapPhoto)
                             .value()

      return { wrappedPhotos }
    },
    computed: {
      topNum () {
        return _.chain(this.roundPhotos)
                .size()
                .divide(5)
                .round()
                .value()
      },
      leftNum () {
        return _.chain(this.roundPhotos)
                .size()
                .subtract(this.topNum)
                .divide(2)
                .round()
                .value()
      },
      rightNum () {
        return _.chain(this.roundPhotos)
                .size()
                .subtract(this.topNum)
                .subtract(this.leftNum)
                .value()
      },
      roundPhotos () {
        return _.reject(this.wrappedPhotos, 'isCenter')
      },
      centerPhoto () {
        return _.find(this.wrappedPhotos, 'isCenter')
      },
    },
    methods: {
      calcPositions () {
        const HEIGHT = this.$el ? this.$el.scrollHeight : 0
        const WIDTH = this.$el ? this.$el.scrollWidth : 0

        const range = {
          top: {
            x: [WIDTH * 0.35, WIDTH * 0.65 - BOX_SIZE.WIDTH],
            y: [0, HEIGHT * 0.3 - BOX_SIZE.HEIGHT],
          },
          left: {
            x: [0, WIDTH * 0.35 - BOX_SIZE.WIDTH],
            y: [0, HEIGHT - BOX_SIZE.HEIGHT],
          },
          right: {
            x: [WIDTH * 0.65, WIDTH - BOX_SIZE.WIDTH],
            y: [0, HEIGHT - BOX_SIZE.HEIGHT],
          },
        }

        const center = {
          x: (WIDTH - BOX_SIZE.WIDTH) / 2,
          y: (HEIGHT - BOX_SIZE.HEIGHT) / 2,
          rotate: 0,
        }

        const topPositions = _.times(this.topNum, () => randomPosition(range.top))
        const leftPositions = _.times(this.leftNum, () => randomPosition(range.left))
        const rightPositions = _.times(this.rightNum, () => randomPosition(range.right))

        let roundPositions = _(topPositions).concat(leftPositions, rightPositions).shuffle().value()

        if (this.centerPhoto) {
          roundPositions = _.concat(
            roundPositions.slice(0, this.centerPhoto.index),
            [center],
            roundPositions.slice(this.centerPhoto.index),
          )
        }

        return roundPositions
      },

      select (centerIndex) {
        const setIsCenter = photo => {
          photo.isCenter = photo.index === centerIndex
          photo.isInverse = photo.isCenter ? photo.isInverse : false
        }

        this.wrappedPhotos = _.chain(this.wrappedPhotos)
                              .clone()
                              .forEach(setIsCenter)
                              .value()

        const positions = this.calcPositions()

        _.zipWith(this.wrappedPhotos, positions, _.assign)
      },

      toggleInverse (index) {
        const photo = this.wrappedPhotos[index]
        photo.isInverse = !photo.isInverse

        this.wrappedPhotos = _.cloneDeep(this.wrappedPhotos)
      },

      shuffle () {
        const centerIndex = _.random(this.wrappedPhotos.length - 1)
        this.select(centerIndex)
      },

      handleClick (index) {
        const photo = this.wrappedPhotos[index]

        if (photo.isCenter) {
          this.toggleInverse(index)
        } else {
          this.select(index)
        }
      },
    },
    mounted () {
      this.shuffle()
    },
  }
</script>

<style lang="scss" scoped>
  .photo-container {
    position: relative;
    width: 100%;
    height: 100%;
  }
</style>
